package com.sophossystems.client.asmon.dao.spring;

import java.sql.SQLException;
import java.util.Date;
import java.util.List;

import com.sophossystems.client.asmon.dao.RutaDao;
import com.sophossystems.client.asmon.dto.RutaDTO;
import com.sophossystems.client.asmon.dto.RutaPkDTO;
import com.sophossystems.client.asmon.exceptions.DaoException;
import com.sophossystems.client.asmon.hibernate.Ruta;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.Query;
import org.hibernate.transform.Transformers;

import org.springframework.orm.hibernate3.HibernateCallback;

import org.apache.log4j.Logger;

public class RutaDaoImpl extends AbstractDAO implements RutaDao{

	private static Logger log = Logger.getLogger(ActivityDaoImpl.class);
	
	@Override
	public RutaPkDTO insert(final RutaDTO rutaDto) {
		RutaPkDTO exito = null;
		try {
			exito = (RutaPkDTO) getHibernateTemplate().execute(new HibernateCallback() {
				
				@Override
				public Object doInHibernate(Session session) throws HibernateException,
						SQLException {
					Transaction tx = session.beginTransaction();
					RutaPkDTO pk = null;
					Ruta ruta = new Ruta();
					ruta.mapper(rutaDto);
					session.save(ruta);
					log.debug("insertando ruta con idCliente = " + rutaDto.getIdCliente());
					int ultimoRegistro = 0;
					try {
						ultimoRegistro =  findLastInsert().getIdRuta();
					} catch (Exception e) {
						log.debug("Error al obtener el antepenultimo registro, causa. " + e.getMessage());
					}
					tx.commit();
					int registroFinal = 0;
					try {
						registroFinal = findLastInsert().getIdRuta();
					} catch (Exception e) {
						log.debug("Error al validar la ultima insersion, causa: " + e.getCause());
					}
					if(registroFinal > ultimoRegistro){
						pk.setIdRuta(registroFinal);
					}
					return pk;
				}
			});
			
		} catch (Exception e) {
			log.error("Error al insertar ruta, causa: " + e.getCause());
		}
		
		return exito;
	}

	@Override
	public void update(final RutaDTO ruta) throws DaoException {
		try {
			getHibernateTemplate().execute(new HibernateCallback() {
				
				@Override
				public Object doInHibernate(Session session) throws HibernateException,
						SQLException {
					RutaPkDTO pk = null;
					RutaDTO rutaDto = null;
					Transaction tx = session.beginTransaction();
//					Verificamos si existe el registro
					try {
						rutaDto = findByPrimaryKey(ruta.getIdRuta());
						pk = new RutaPkDTO();
						pk.setIdRuta(rutaDto.getIdRuta());
					} catch (DaoException e) {
						throw new HibernateException("error consulta ruta para update, causa: " + e.getMessage());
					}
//					Actuliza los campos con los datos de entrada
					Ruta persis = new Ruta();
					persis.mapper(ruta);
					persis.setIdRuta(pk.getIdRuta());
					session.update(persis);
					tx.commit();
					return null;
				}
			});
		} catch (Exception e) {
			log.error("Error al actualizar registro, causa: " + e.getMessage());
			throw new DaoException("Error update ruta, causa: " + e.getCause());
		}
		
	}

	@Override
	public void delete(final RutaPkDTO pk) throws DaoException {
		try {
			getHibernateTemplate().execute(new HibernateCallback() {
				
				@Override
				public Object doInHibernate(Session session) throws HibernateException,
						SQLException {
					Transaction tx = session.beginTransaction();
					Ruta ruta = (Ruta) session.load(Ruta.class, pk.getIdRuta());
					session.delete(ruta);
					tx.commit();
					return null;
				}
			});
		} catch (Exception e) {
			log.error("Error delete ruta, causa: " + e.getCause());
			throw new DaoException("Delete error Ruta causa: " + e.getCause());
		}
		
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<RutaDTO> findByIdCliente(final int idCliente) throws DaoException {
		List<RutaDTO> exito = null;
		try {
			exito = (List<RutaDTO>) getHibernateTemplate().execute(new HibernateCallback() {
				
				@Override
				public Object doInHibernate(Session session) throws HibernateException,
						SQLException {
					 final Query oQuery = session.createQuery("SELECT r.idRuta as idRuta, r.idCliente as idCliente, r.idMensajero as idMensajero" +
								", r.idZona as idZona, r.fechaRuta as fechaRuta r.fechaDoc as fechaDoc, r.comentarioCierre as comentarioCierre, " +
								"r.folioApertura as folioApertura, r.cierreRuta as cierreRuta, r.fechaRuta as fechaRuta FROM "
								+ getTableName() +
								" r WHERE r.idCliente = :idCliente");
						oQuery.setInteger("idCliente", idCliente);
						List<RutaDTO> rutaDto = (List<RutaDTO>) oQuery.setResultTransformer(Transformers
								.aliasToBean(RutaDTO.class)).list();
						log.info("Se obtienen " + rutaDto.size() + " resultados");
					return rutaDto;
				}
			});
		} catch (Exception e) {
			log.error("error al buscar ruta idCliente, causa: " + e.getCause());
			throw new DaoException("RutaDaoImpl error, causa: " + e.getCause());
		}
		return exito;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<RutaDTO> findByIdMensajero(final int idMensajero) throws DaoException {
		List<RutaDTO> exito = null;
		try {
			exito = (List<RutaDTO>) getHibernateTemplate().execute(new HibernateCallback() {
				
				@Override
				public Object doInHibernate(Session session) throws HibernateException,
						SQLException {
					 final Query oQuery = session.createQuery("SELECT r.idRuta as idRuta, r.idCliente as idCliente, r.idMensajero as idMensajero" +
								", r.idZona as idZona, r.fechaRuta as fechaRuta, r.fechaDoc as fechaDoc, r.comentarioCierre as comentarioCierre, " +
								"r.folioApertura as folioApertura, r.cierreRuta as cierreRuta, r.fechaRuta as fechaRuta FROM "
								+ getTableName() + " r WHERE r.idMensajero = :idMensajero");
						oQuery.setInteger("idMensajero", idMensajero);
						List<RutaDTO> rutaDto = (List<RutaDTO>) oQuery.setResultTransformer(Transformers
								.aliasToBean(RutaDTO.class)).list();
						log.info("Se obtienen " + rutaDto.size() + " resultados");
					return rutaDto;
				}
			});
		} catch (Exception e) {
			log.error("error al buscar ruta idMensajero, causa: " + e.getCause());
			throw new DaoException("RutaDaoImpl error, causa: " + e.getCause());
		}
		return exito;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<RutaDTO> findByDate(final Date fecha) throws DaoException {
		List<RutaDTO> exito = null;
		try {
			exito = (List<RutaDTO>) getHibernateTemplate().execute(new HibernateCallback() {
				
				@Override
				public Object doInHibernate(Session session) throws HibernateException,
						SQLException {
					 final Query oQuery = session.createQuery("SELECT r.idRuta as idRuta, r.idCliente as idCliente, r.idMensajero as idMensajero" +
								", r.idZona as idZona, r.fechaRuta as fechaRuta r.fechaDoc as fechaDoc, r.comentarioCierre as comentarioCierre, " +
								"r.folioApertura as folioApertura, r.cierreRuta as cierreRuta, r.fechaRuta as fechaRuta FROM "
								+ getTableName() +
								" r WHERE r.fechaRuta = :fecha");
						oQuery.setDate("fecha", fecha);
						List<RutaDTO> rutaDto = (List<RutaDTO>) oQuery.setResultTransformer(Transformers
								.aliasToBean(RutaDTO.class)).list();
						log.info("Se obtienen " + rutaDto.size() + " resultados");
					return rutaDto;
				}
			});
		} catch (Exception e) {
			log.error("error al buscar ruta idMensajero, causa: " + e.getCause());
			throw new DaoException("RutaDaoImpl error, causa: " + e.getCause());
		}
		return exito;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<RutaDTO> buscarRangoFecha(final Date fInicio, final Date fFinal)
			throws DaoException {
		List<RutaDTO> exito = null;
		try {
			exito = (List<RutaDTO>) getHibernateTemplate().execute(new HibernateCallback() {
				
				@Override
				public Object doInHibernate(Session session) throws HibernateException,
						SQLException {
					 final Query oQuery = session.createQuery("SELECT r.idRuta as idRuta, r.idCliente as idCliente, r.idMensajero as idMensajero" +
								", r.idZona as idZona, r.fechaRuta as fechaRuta r.fechaDoc as fechaDoc, r.comentarioCierre as comentarioCierre, " +
								"r.folioApertura as folioApertura, r.cierreRuta as cierreRuta, r.fechaRuta as fechaRuta FROM "
								+ getTableName() +
								" r WHERE r.fechaRuta BETWEEN :fechaIni AND :fechaFinal");
						oQuery.setDate("fechaIni", fInicio);
						oQuery.setDate("fechaFinal", fFinal);
						List<RutaDTO> rutaDto = (List<RutaDTO>) oQuery.setResultTransformer(Transformers
								.aliasToBean(RutaDTO.class)).list();
						log.info("Se obtienen " + rutaDto.size() + " resultados");
					return rutaDto;
				}
			});
		} catch (Exception e) {
			log.error("error al buscar ruta idMensajero, causa: " + e.getCause());
			throw new DaoException("RutaDaoImpl error, causa: " + e.getCause());
		}
		return exito;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<RutaDTO> findByIdZona(final int idZona) throws DaoException {
		List<RutaDTO> exito = null;
		try {
			exito = (List<RutaDTO>) getHibernateTemplate().execute(new HibernateCallback() {
				
				@Override
				public Object doInHibernate(Session session) throws HibernateException,
						SQLException {
					 final Query oQuery = session.createQuery("SELECT r.idRuta as idRuta, r.idCliente as idCliente, r.idMensajero as idMensajero" +
								", r.idZona as idZona, r.fechaRuta as fechaRuta r.fechaDoc as fechaDoc, r.comentarioCierre as comentarioCierre, " +
								"r.folioApertura as folioApertura, r.cierreRuta as cierreRuta, r.fechaRuta as fechaRuta FROM "
								+ getTableName() +
								" r WHERE r.idZona = :idZona");
						oQuery.setInteger("idZona", idZona);
						List<RutaDTO> rutaDto = (List<RutaDTO>) oQuery.setResultTransformer(Transformers
								.aliasToBean(RutaDTO.class)).list();
						log.info("Se obtienen " + rutaDto.size() + " resultados");
					return rutaDto;
				}
			});
		} catch (Exception e) {
			log.error("error al buscar ruta idZona, causa: " + e.getCause());
			throw new DaoException("RutaDaoImpl error, causa: " + e.getCause());
		}
		return exito;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<RutaDTO> findByIdCierreRuta (final int idStatus) throws DaoException {
		List<RutaDTO> exito = null;
		/*
		 * 0 = abierto
		 * 1 = cerrado
		 * 3 = cancelado
		 */
		try {
			exito = (List<RutaDTO>) getHibernateTemplate().execute(new HibernateCallback() {
				
				@Override
				public Object doInHibernate(Session session) throws HibernateException,
						SQLException {
					 final Query oQuery = session.createQuery("SELECT r.idRuta as idRuta, r.idCliente as idCliente, r.idMensajero as idMensajero" +
								", r.idZona as idZona, r.fechaRuta as fechaRuta r.fechaDoc as fechaDoc, r.comentarioCierre as comentarioCierre, " +
								"r.folioApertura as folioApertura, r.cierreRuta as cierreRuta, r.fechaRuta as fechaRuta FROM "
								+ getTableName() +
								" r WHERE r.cierreRuta = :idStatus");
						oQuery.setInteger("idStatus", idStatus);
						List<RutaDTO> rutaDto = (List<RutaDTO>) oQuery.setResultTransformer(Transformers
								.aliasToBean(RutaDTO.class)).list();
						log.info("Se obtienen " + rutaDto.size() + " resultados");
					return rutaDto;
				}
			});
		} catch (Exception e) {
			log.error("error al buscar ruta idZona, causa: " + e.getCause());
			throw new DaoException("RutaDaoImpl error, causa: " + e.getCause());
		}
		return exito;
		
	}

	@Override
	public RutaPkDTO findLastInsert() throws DaoException {
		RutaPkDTO ruta = null;
		try {
			ruta = (RutaPkDTO) getHibernateTemplate().execute(
					new HibernateCallback() {

						@Override
						public Object doInHibernate(Session session)
								throws HibernateException, SQLException {
							
							Query oQuery = session
									.createQuery("SELECT max(r.idRuta) as idRuta FROM "
											+ getTableName()
											+ " r ");
							
							RutaPkDTO RutaDto = (RutaPkDTO) oQuery
									.setResultTransformer(Transformers
											.aliasToBean(RutaPkDTO.class)).list().get(0);
							return RutaDto;
						}
					});
		
		} catch (Exception e) {
			logger.error("Error: Ruta, cause: " + e.getMessage(), e);
			throw new DaoException("Query failed", e);
		}
		return ruta;
	}
	
	/**
	 * Method 'getTableName'
	 * 
	 * @return String
	 */
	public String getTableName() {
		return "Ruta";
	}

	@Override
	public RutaDTO findByPrimaryKey(final int idRuta) throws DaoException {
		RutaDTO rutaPk = null;
		try {
			rutaPk = (RutaDTO) getHibernateTemplate().execute(new HibernateCallback() {
				
				@Override
				public Object doInHibernate(Session session) throws HibernateException,
						SQLException {
					final Query oQuery = session.createQuery("SELECT r.idRuta as idRuta, r.idCliente as idCliente, r.idMensajero as idMensajero" +
							", r.idZona as idZona, r.fechaRuta as fechaRuta r.fechaDoc as fechaDoc, r.comentarioCierre as comentarioCierre, " +
							"r.folioApertura as folioApertura, r.cierreRuta as cierreRuta, r.fechaRuta as fechaRuta FROM "
							+ getTableName() +
							" r WHERE r.idRuta = :idRuta");
					oQuery.setInteger("idRuta", idRuta);
					RutaDTO rutaDto = (RutaDTO) oQuery.setResultTransformer(Transformers
							.aliasToBean(RutaDTO.class)).list().get(0);
					return rutaDto;
				}
			});
		} catch (Exception e) {
			log.error("Error findByPrimaryKey, causa: " + e.getCause());
			throw new DaoException("Error: " + e.getCause());
		}
		return rutaPk;
	}

}
